package org.spring.springboot.app.onlinepay.service.impl;


import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spring.springboot.app.agent.balancelog.domain.po.SysOfficeBalanceLogPO;
import org.spring.springboot.app.agent.balancelog.service.ISysOfficeBalanceLogService;
import org.spring.springboot.app.base.Constants;
import org.spring.springboot.app.onlinepay.dao.OnlinePayLogDao;
import org.spring.springboot.app.onlinepay.dao.OnlinePayDao;
import org.spring.springboot.app.onlinepay.domain.po.OnlinePayLogPO;
import org.spring.springboot.app.onlinepay.domain.po.OnlinePayPO;
import org.spring.springboot.app.onlinepay.service.IOnlinePayService;
import org.spring.springboot.app.sys.office.dao.SysOfficeDao;
import org.spring.springboot.app.sys.office.domain.po.SysOfficeWalletPO;
import org.spring.springboot.app.sys.office.service.ISysOfficeService;
import org.spring.springboot.util.Arith;
import org.spring.springboot.util.IdGen;
import org.spring.springboot.util.NumberUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class OnlinePayServiceImpl implements IOnlinePayService {

    private static final Logger LOGGER = LoggerFactory.getLogger(OnlinePayServiceImpl.class);

    @Autowired
    private OnlinePayDao dao;
    @Autowired
    private OnlinePayLogDao logDao;
    @Autowired
    private SysOfficeDao sysOfficeDao;
    @Autowired
    private ISysOfficeService sysOfficeService;
    @Autowired
    private ISysOfficeBalanceLogService sysOfficeBalanceLogService;

    @Override
    public int save(OnlinePayPO po){
        po.preInsert();
        if(po.getUserId()==null){
            po.setUserId(po.getCreateBy());
        }
        po.setCreatetime(po.getCreateDate());
        return dao.insertSelective(po);
    }

    @Override
    public int checkPayState(String id){
        OnlinePayPO po=dao.selectByPrimaryKey(id);
        return po.getState();
    }
    /**
     * 支付宝处理异步回调
     * @param request
     * @param response
     * @param validatelist
     * @param successState
     * @param title
     */
    @Override
    public void doAlipay(HttpServletRequest request, HttpServletResponse response, List<String> validatelist, String successState, String title){
            Map<String, String> params = new HashMap<String, String>();
            Map<String, String[]> requestParams = request.getParameterMap();
            //解析参数
            for(Map.Entry<String, String[]> entry : requestParams.entrySet()){
                String name = entry.getKey();
                String[] values = entry.getValue();
                if(values != null && values.length > 0){
                    StringBuilder sb = new StringBuilder();
                    for(int i = 0; i < values.length; i++) {
                        sb.append(values[i]);
                        if(i < values.length - 1){
                            sb.append(",");
                        }
                    }
                    params.put(name, sb.toString());
                }
            }
            // 取得参数
            String sellerId = params.get("seller_id");
            String returnCode = params.get("trade_status");
            String orderId = params.get("out_trade_no");
            String totalFee = params.get("total_fee");
            totalFee=totalFee==null?params.get("total_amount"):totalFee;
            int status = Constants.ONLINE_PAY_CALL_ZERO;
            //检查权限是否正确
            if (validatelist.contains(sellerId.toLowerCase()) && successState.equalsIgnoreCase(returnCode)) {
                //换算成元
                double _dealMoney = NumberUtil.parseDouble(totalFee);
                //处理订单
                 status = operateOnlineOrder(orderId, _dealMoney, Constants.ONLINE_PAY_ACTION_DEALFROM_1);
            }
            LogFactory.getLog(this.getClass()).info(title+ " status:"+status);
            //添加日志记录
            OnlinePayLogPO logPo =new OnlinePayLogPO();
            logPo.setPnid(IdGen.uuid());
            logPo.setPnpayid(orderId);
            logPo.setPncreatetime(new Date());
            ObjectMapper mapper = new ObjectMapper();
            try {
                logPo.setPncontent( mapper.writeValueAsString(params));
            } catch (Exception e) {
                LogFactory.getLog(this.getClass()).error(title, e);
            }
            logPo.setPncontenttype(Constants.ONLINE_PAY_CALL_BACK_SOURCE_2);
            logDao.insert(logPo);
            //如果订单状态已成功，则直接返回成功
            if(status == Constants.ONLINE_PAY_CALL_ZERO){
                 status = checkOnlineOrder(orderId);
            }
            try {
                PrintWriter witer = response.getWriter();
                if (status == Constants.ONLINE_PAY_CALL_SUCCESS) {
                   LogFactory.getLog(this.getClass()).info(title + " call back.success");
                    witer.println("success");
                } else {
                    witer.println("fail");
                }
            } catch (Exception e) {
                LogFactory.getLog(this.getClass()).error(title, e);
            }
    }

    /**
     *微信处理异步回调
     * @param request
     * @param response
     * @param validatelist
     * @param successState
     * @param title
     */
    @Override
    public void doWeiXin(HttpServletRequest request, HttpServletResponse response, List<String> validatelist, String successState, String title){
            try{
                InputStream stream = request.getInputStream();
                PrintWriter witer = response.getWriter();
                SAXReader reader = new SAXReader();
                Document document = reader.read(stream);
                Element root = document.getRootElement();
                // 公众号ID
                String appId = root.elementText("appid");
                // 商户ID
                String mchId = root.elementText("mch_id");
                // 返回代码，判断SUCCESS
                String returnCode = root.elementText("return_code");
                // 充值订单号，支付订单号
                String orderId = root.elementText("out_trade_no");
                // 总支付金额，单位分
                String totalFee = root.elementText("total_fee");
                LogFactory.getLog(this.getClass()).info(title+" orderId:"+orderId);
                int status = Constants.ONLINE_PAY_CALL_ZERO;
                //检查权限是否正确
                if (validatelist.contains((appId+mchId).toLowerCase())
                        && successState.equalsIgnoreCase(returnCode)) {
                    //long _orderId = NumberUtil.parseLong(orderId);
                    //换算成元
                    double _dealMoney = Arith.div(NumberUtil.parseDouble(totalFee) ,100.00d);
                    //处理订单
                    status = operateOnlineOrder(orderId, _dealMoney, Constants.ONLINE_PAY_ACTION_DEALFROM_1);
                }
                // 添加回调记录
                OnlinePayLogPO logPo =new OnlinePayLogPO();
                logPo.setPnid(IdGen.uuid());
                logPo.setPnpayid(orderId);
                logPo.setPncontent(root.asXML());
                logPo.setPncontenttype(Constants.ONLINE_PAY_CALL_BACK_SOURCE_1);
                logDao.insert(logPo);
                //如果订单状态已成功，则直接返回成功
                if(status == Constants.ONLINE_PAY_CALL_ZERO){
                    status = checkOnlineOrder(orderId);
                }
                if (status == Constants.ONLINE_PAY_CALL_SUCCESS) {
                    LogFactory.getLog(this.getClass()).info(title+" call back.success");
                    witer.write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
                } else {
                    witer.write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>");
                }
            } catch (Exception e) {
                LogFactory.getLog(this.getClass()).error(title, e);
            }
    }

    /**
     * 检查 订单
     * @param orderId
     * @return
     */
    private int checkOnlineOrder(String orderId) {
        int status = Constants.ONLINE_PAY_CALL_ZERO;
        OnlinePayPO po = null;
        //检查订单是否存在
        if (status == Constants.ONLINE_PAY_CALL_ZERO) {
            po = dao.selectByPrimaryKey(orderId);
            if (po == null) {
                status = Constants.ONLINE_PAY_CALL_FAIL;
            }
        }
        //检查订单是否处理成功
        if (status == Constants.ONLINE_PAY_CALL_ZERO) {
            if (po.getState() == Constants.ONLINE_PAY_CALL_SUCCESS) {
                status = Constants.ONLINE_PAY_CALL_SUCCESS;
            }
        }
        return status;
    }
    /**
     * 
     */
    /**
     * 处理订单
     * @param orderId
     * @param dealMoney
     * @param dealFrom
     * @return
     */
    private int operateOnlineOrder(String orderId, double dealMoney, int dealFrom) {
        dealMoney = Arith.decimalFormat2(dealMoney);
        int status = Constants.ONLINE_PAY_CALL_ZERO;
        OnlinePayPO po = null;
        //检查订单是否存在
        if (status == Constants.ONLINE_PAY_CALL_ZERO) {
            po = dao.selectByPrimaryKey(orderId);
            if (po == null) {
                status = Constants.ONLINE_PAY_CALL_FAIL;
            }
        }
        //检查订单是否处理成功
        if (status == Constants.ONLINE_PAY_CALL_ZERO) {
            if (po.getState() == Constants.ONLINE_PAY_CALL_SUCCESS) {
                status = Constants.ONLINE_PAY_CALL_SUCCESS;
            }
        }
        //检查金额是否对等
        if (status == Constants.ONLINE_PAY_CALL_ZERO) {
            double orderMoney = po.getMoney();
            if (dealMoney != orderMoney) {
                status = Constants.ONLINE_PAY_CALL_FAIL;
            }
        }
        if (status == Constants.ONLINE_PAY_CALL_ZERO) {
            int type  = po.getType();
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> resultMap = new HashMap<String, Object>();
            if(StringUtils.isNotBlank(po.getJsondata())){
                try{
                     resultMap= mapper.readValue(po.getJsondata(),Map.class);
                } catch (Exception e){
                    e.printStackTrace();
                    resultMap = new HashMap<String, Object>();
                }
            }
            switch (type) {
                // TODO 处理各种充值逻辑
                case Constants.ONLINEPAY_OPERATION_TYPE_1: //代理商充值余额
                    SysOfficeWalletPO walletPO = sysOfficeDao.queryWallet(resultMap.get("officeId").toString());
                    walletPO.setOldBalance(walletPO.getBalance());
                    walletPO.setBalance(BigDecimal.valueOf(Arith.add(NumberUtil.parseDouble(walletPO.getBalance()),dealMoney)));
                    if (sysOfficeDao.updateWallet(walletPO) >0) {
                        status = Constants.ONLINE_PAY_CALL_SUCCESS;
                        //添加机构钱包日志
                        SysOfficeBalanceLogPO balanceLogPO = new SysOfficeBalanceLogPO();
                        balanceLogPO.setOfficeId(walletPO.getId());
                        balanceLogPO.setType(Constants.SYS_OFFICE_BALANCE_LOG_TYPE_100);
                        balanceLogPO.setMoney(BigDecimal.valueOf(dealMoney));
                        balanceLogPO.setRelateId(orderId);
                        balanceLogPO.preInsert();
                        sysOfficeBalanceLogService.save(balanceLogPO);
                    }
                    break;
                default:
                    break;
            }
            // 更新处理状态
            po.preUpdate();
            po.setState(status);
            po.setDealtime(po.getUpdateDate());
            po.setDealfrom(dealFrom);
            dao.updateByPrimaryKeySelective(po);
        }
        return status;
    }

    /**
     * 通过订单类型
     * @param type
     * @return
     */
    @Override
    public String getJsonData(int type){
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> resultMap = new HashMap<String, Object>();
        OnlinePayPO po = new OnlinePayPO();
        switch (type) {
            //TODO 对应逻辑下需要组装的JSDATA
            case Constants.ONLINEPAY_OPERATION_TYPE_1: //代理商充值余额
                resultMap.put("officeId",po.getUser().getOfficeId());
                break;
            default:
                break;
        }
        try {
            return mapper.writeValueAsString(resultMap);
        }catch (Exception e){
            e.printStackTrace();
            return  "";
        }
    }

    /**
     *
     * @param id
     * @return
     */
    @Override
    public  OnlinePayPO selectByPrimaryKey(String id){
        return  dao.selectByPrimaryKey(id);
    }
}
